/*
 * 从形状注入资源过滤器 - 将形状渲染为脚本并注入到页面
 * 
 * 主要功能：
 * - 将形状渲染为HTML脚本
 * - 将渲染的脚本注入到页面头部或底部
 * - 演示IDisplayHelper的使用
 * - 结合形状系统和资源管理系统
 */

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using OrchardCore.DisplayManagement;
using OrchardCore.ResourceManagement;
using System.Threading.Tasks;

namespace Lombiq.TrainingDemo.Filters;

/// <summary>
/// 从形状注入资源过滤器 - 将形状渲染为脚本并注入到页面
/// 
/// 主要用途：
/// - 将形状渲染为HTML脚本
 /* - 将渲染的脚本注入到页面头部或底部
 * - 演示IDisplayHelper的使用
 * - 结合形状系统和资源管理系统
 * 
 * 使用场景：
 * - 根据URL参数动态生成脚本
 * - 将形状内容作为内联脚本注入
 * - 在后台任务中生成HTML输出
 * - 为邮件模板生成HTML内容
 * 
 * 设计原因：
 * - 提供动态脚本生成机制
 * - 演示形状系统的强大功能
 * - 实现条件性脚本注入
 * - 提供可重用的脚本生成功能
 * 
 * 设计模式：
 * - 过滤器模式：实现IAsyncResultFilter接口
 * - 依赖注入模式：通过构造函数注入服务
 * - 形状模式：使用IShapeFactory创建形状
 * - 显示模式：使用IDisplayHelper渲染形状
 * - 资源管理模式：使用IResourceManager注册脚本*/
/// </summary>
public sealed class ResourceFromShapeInjectingFilter : IAsyncResultFilter
{
    // 我们之前见过IResourceManager和IShapeFactory。
    private readonly IResourceManager _resourceManager;

    private readonly IShapeFactory _shapeFactory;

    // IDisplayHelper是新的，但是。我们将使用它来将形状执行到HTML中，并将其作为头部脚本注入！
    private readonly IDisplayHelper _displayHelper;

    /// <summary>
    /// 构造函数 - 注入所需的服务依赖
    /// </summary>
    /// <param name="resourceManager">资源管理器，用于注册脚本</param>
    /// <param name="shapeFactory">形状工厂，用于创建形状</param>
    /// <param name="displayHelper">显示帮助器，用于渲染形状</param>
    public ResourceFromShapeInjectingFilter(
        IResourceManager resourceManager,
        IShapeFactory shapeFactory,
        IDisplayHelper displayHelper)
    {
        _resourceManager = resourceManager;
        _shapeFactory = shapeFactory;
        _displayHelper = displayHelper;
    }

    /// <summary>
    /// 结果执行方法 - 在结果执行时注入形状渲染的脚本
    /// 
    /// 功能说明：
    /// - 检查结果类型是否为PartialViewResult
    /// - 检查URL是否包含"alert"查询参数
    /// - 创建AlertScriptShape形状
    /// - 渲染形状为HTML内容
    /// - 将HTML内容注册为脚脚脚本
    /// 
    /// 执行条件：
    /// - 不是部分视图结果
    /// - URL包含"alert"查询参数
    /// 
    /// 使用示例：
    /// - 在任何页面URL后添加"?alert"或"&alert"
    /// - 观察动态生成的脚本效果
    /// 
    /// 技术特点：
    /// - 使用形状系统生成动态内容
    /// - 将形状渲染为HTML脚本
    /// - 支持内联脚本注入
    /// - 可用于后台任务和邮件模板
    /// </summary>
    /// <param name="context">结果执行上下文</param>
    /// <param name="next">下一个执行委托</param>
    /// <returns>完成的任务</returns>
    public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
    {
        // 类似于ResourceInjectionFilter，只有在完整视图中且存在"alert"查询字符串参数时才运行此过滤器。
        // 只需打开任何页面并在URL中添加"?alert"或"&alert"，然后看看会发生什么！
        if (context.Result is PartialViewResult || !context.HttpContext.Request.Query.ContainsKey("alert"))
        {
            await next();

            return;
        }

        // 我们再次使用形状工厂来实例化AlertScriptShape。查看Views/AlertScriptShape.cshtml，
        // 因为那里也有一些有趣的东西，然后回来！接下来，我们还使用显示帮助器来执行形状并生成其HTML内容。
        var shapeContent = await _displayHelper.ShapeExecuteAsync(await _shapeFactory.New.AlertScriptShape());

        // 您知道您也可以用资源管理器注入内联脚本吗？您可以使用这种技术不仅像这样生成内联脚本，
        // 而且还可以例如在后台任务中从形状生成HTML输出（比如在发送电子邮件时，您希望为它们提供适当的模板）。
        _resourceManager.RegisterFootScript(shapeContent);

        await next();
    }
}

/// <summary>
/// 训练部分结束说明
/// 
/// 本节内容：
/// - 利用动作和结果过滤器
 /* - 演示形状系统的强大功能
 * - 展示资源管理的灵活应用
 * - 结合多个Orchard Core系统*/
/// </summary>
// 训练部分结束：利用动作和结果过滤器

// 下一站：Services/ShapeHidingShapeTableProvider.cs
